package shelfGrid

import (
	"context"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"github.com/kuangshp/go-utils/k"
	"golang.org/x/sync/errgroup"
	"gorm.io/gorm"
	"insighttracking/apps/admin/auth"
	"insighttracking/apps/admin/internal/svc"
	"insighttracking/apps/admin/internal/types"
	types2 "insighttracking/common/types"
	"insighttracking/common/utils"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"
	"strconv"

	"github.com/zeromicro/go-zero/core/logx"
	"os"
)

type ApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *ApiLogic {
	hostname, _ := os.Hostname()
	return &ApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

func (l *ApiLogic) CreateApi(req *types.CreateShelfGridReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}

	codes := make([]string, 0)
	codes = append(codes, req.Code)
	entities, err := service.ShelfGridService.GetSameCodeApi(l.ctx, accountInfo.EnterpriseId, req.ShelfId, codes)
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return "", errors.New("已存在相同的货位编号：" + entities.Code)
	}

	if err = service.ShelfGridService.CreateApi(l.ctx, model.ShelfGridEntity{
		Code:            req.Code, // 仓库编码
		EnterpriseID:    accountInfo.EnterpriseId,
		WarehouseID:     req.WarehouseID,
		WarehouseAreaID: req.WarehouseAreaID,
		ShlefID:         req.ShelfId,
		IsTemp:          req.IsTemp,
		Describe:        req.Describe,
		CreatedBy:       accountInfo.PersonId,
	}); err != nil {
		return "", errors.New(err.Error())
	}
	return "操作成功", nil
}

func (l *ApiLogic) BatchCreateApi(req *types.BatchCreateShelfGridReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}

	codes := make([]string, 0)
	for _, item := range req.ShelfGrids {
		codes = append(codes, item.Code)
	}

	entities, err := service.ShelfGridService.GetSameCodeApi(l.ctx, accountInfo.EnterpriseId, req.ShelfGrids[0].ShelfId, codes)
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return "", errors.New("已存在相同的货位编号：" + entities.Code)
	}

	shelfGrids := make([]*model.ShelfGridEntity, 0)
	for _, item := range req.ShelfGrids {
		shelfGrids = append(shelfGrids, &model.ShelfGridEntity{
			Code:            item.Code,
			EnterpriseID:    accountInfo.EnterpriseId,
			WarehouseID:     item.WarehouseID,
			WarehouseAreaID: item.WarehouseAreaID,
			ShlefID:         item.ShelfId,
			IsTemp:          item.IsTemp,
			Describe:        item.Describe,
			CreatedBy:       accountInfo.PersonId,
		})
	}
	if err = service.ShelfGridService.BatchCreateApi(l.ctx, shelfGrids); err != nil {
		return "", errors.New(err.Error())
	}
	return "操作成功", nil
}

func (l *ApiLogic) GetNewCode(req *types.CreateShelfGridCodeReq) (resp types.CreateShelfGridCodeResp, err error) {
	resp = types.CreateShelfGridCodeResp{}
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	g, ctx := errgroup.WithContext(l.ctx)
	shelf := &model.ShelfEntity{}
	warehouseArea := &model.WarehouseAreaEntity{}
	g.Go(func() (err error) {
		shelf, err = service.ShelfService.GetSelfByIdApi(ctx, req.ShelfId)
		return
	})
	g.Go(func() (err error) {
		warehouseArea, err = service.WarehouseAreaService.GetByIdApi(ctx, accountInfo.EnterpriseId, req.WarehouseID, req.WarehouseAreaID)
		return
	})
	if err = g.Wait(); err != nil {
		return resp, errors.New("参数错误")
	}

	var separator string
	if req.IsEnableSeparator == 1 {
		separator = "-"
	}
	prefix := warehouseArea.Code + separator + shelf.Code + separator
	count, err := service.ShelfGridService.GetCountByShelfIdApi(l.ctx, accountInfo.EnterpriseId, req.ShelfId)
	code := prefix + fmt.Sprintf("%04d", int(count)+1)
	resp = types.CreateShelfGridCodeResp{
		Code: code,
	}
	return
}

func (l *ApiLogic) BatchGetNewCode(req *types.BatchCreateShelfGridCodeReq) (resp types.BatchCreateShelfGridCodeResp, err error) {
	resp = types.BatchCreateShelfGridCodeResp{}
	grids := make([]*types.ShelfGridPreviewResp, req.GridRow*req.GridColumn)
	resp.ShelfGrids = grids
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	g, ctx := errgroup.WithContext(l.ctx)
	shelf := &model.ShelfEntity{}
	warehouseArea := &model.WarehouseAreaEntity{}
	g.Go(func() (err error) {
		shelf, err = service.ShelfService.GetSelfByIdApi(ctx, req.ShelfId)
		return
	})
	g.Go(func() (err error) {
		warehouseArea, err = service.WarehouseAreaService.GetByIdApi(ctx, accountInfo.EnterpriseId, req.WarehouseID, req.WarehouseAreaID)
		return
	})
	if err = g.Wait(); err != nil {
		return resp, errors.New("参数错误")
	}

	var separator string
	if req.IsEnableSeparator == 1 {
		separator = "-"
	}
	prefix := warehouseArea.Code + separator + shelf.Code + separator
	list, err := service.ShelfGridService.GetListApi(l.ctx, accountInfo.EnterpriseId, req.ShelfId)
	existingCombinations := make(map[string]bool)
	for _, item := range list {
		key := fmt.Sprintf("%d-%d", item.GridRow, item.GridColumn)
		existingCombinations[key] = true
	}
	for i := 1; i <= req.GridRow; i++ {
		for j := 1; j <= req.GridColumn; j++ {
			var isExist int8 = 0
			key := fmt.Sprintf("%d-%d", i, j)
			if existingCombinations[key] {
				isExist = 1
			}
			grids[(i-1)*req.GridColumn+j-1] = &types.ShelfGridPreviewResp{
				Code:       prefix + strconv.Itoa(i) + separator + strconv.Itoa(j),
				GridRow:    i,
				GridColumn: j,
				IsExist:    isExist,
			}
		}
	}
	return
}

func (l *ApiLogic) DeleteByIdApi(req *types.IdReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}
	// TODO 判断不能删除的情况

	if err = service.ShelfGridService.DeleteByIdApi(l.ctx, accountInfo.EnterpriseId, req.Id); err != nil {
		return "", err
	}
	return "操作成功", nil
}

func (l *ApiLogic) GetListApi(req *types.IdReq) (resp []types.GetShelfGridListResp, err error) {
	resp = make([]types.GetShelfGridListResp, 0)
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	shelfGrids, err := service.ShelfGridService.GetListApi(l.ctx, accountInfo.EnterpriseId, req.Id)
	if err != nil {
		return
	}

	createdIds := make([]int64, 0)
	for _, shelfGrid := range shelfGrids {
		createdIds = append(createdIds, shelfGrid.CreatedBy)
	}
	createdIdAndName := make(map[int64]string)
	personEntities, err := service.EnterprisePersonService.GetByIdListApi(l.ctx, accountInfo.EnterpriseId, createdIds)
	if len(personEntities) > 0 {
		for _, personEntity := range personEntities {
			createdIdAndName[personEntity.ID] = personEntity.Name
		}
	}

	return k.Map(shelfGrids, func(item *model.ShelfGridEntity, index int) types.GetShelfGridListResp {
		var createdName string
		if _, ok := createdIdAndName[item.CreatedBy]; ok {
			createdName = createdIdAndName[item.CreatedBy]
		}
		return types.GetShelfGridListResp{
			ID:          item.ID,   // 主键id
			Code:        item.Code, // 仓库编码
			IsTemp:      item.IsTemp,
			Describe:    item.Describe,
			CreatedBy:   item.CreatedBy,
			CreatedName: createdName,
			CreatedAt:   utils.TimestampToString(item.CreatedAt),
		}
	}), nil
}

func (l *ApiLogic) GetAvailableGridApi(req *types.GetAvailableGridReq) (resp *types.GetAvailableGridResp, err error) {
	list := make([]*types2.SimpleList, 0)
	resp = &types.GetAvailableGridResp{}

	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	shelfGridEntities, err := service.ShelfGridService.GetListByWarehouseIDApi(l.ctx, accountInfo.EnterpriseId, req.WarehouseId)
	gridIDs, err := service.SpuShelfGridInventoryService.GetUsedGridBySpuApi(l.ctx, accountInfo.EnterpriseId, req.SpuID)
	for _, shelfGridEntity := range shelfGridEntities {
		if len(gridIDs) == 0 || !k.IsContains(gridIDs, shelfGridEntity.ID) {
			list = append(list, &types2.SimpleList{
				ID:   shelfGridEntity.ID,
				Code: shelfGridEntity.Code,
			})
		}
	}
	resp.GridBatchNumbers = list
	return
}

func (l *ApiLogic) GetAvailableBatchNumberApi(req *types.GetAvailableBatchNumberReq) (resp *types.GetAvailableBatchNumberResp, err error) {
	list := make([]*types.GridBatchNumber, 0)
	resp = &types.GetAvailableBatchNumberResp{}

	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return
	}

	shelves, err := service.ShelfService.GetListByWarehouseIDApi(l.ctx, accountInfo.EnterpriseId, req.WarehouseID)
	shelfIds := make([]int64, 0)
	for _, shelf := range shelves {
		shelfIds = append(shelfIds, shelf.ID)
	}
	spuShelfGridInventoryEntities, err := service.SpuShelfGridInventoryService.GetBySpuIDApi(l.ctx, accountInfo.EnterpriseId, req.SpuID, "")
	for _, entity := range spuShelfGridInventoryEntities {
		if entity.SupplierID == req.SupplierID && k.IsContains(shelfIds, entity.ShelfID) {
			list = append(list, &types.GridBatchNumber{
				ShelfId:     entity.ShelfGridID,
				BatchNumber: entity.BatchNumber,
			})
		}
	}
	resp.BatchNumbers = list
	return
}

func (l *ApiLogic) GetStoreListApi(req *types.GetGridStoreReq) (resp *types.GetGridStoreResp, err error) {
	return
}
